package org.wangle.seckill.mq.customer;

import com.alibaba.fastjson.JSON;
import com.rabbitmq.client.Channel;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.wangle.api.goods.pojo.Goods;
import org.wangle.api.goods.provider.GoodsProvider;
import org.wangle.api.order.pojo.Orders;
import org.wangle.api.order.provider.OrdersProvider;
import org.wangle.api.properties.MQ.SecKillProperties;
import org.wangle.seckill.mq.component.publisher.SecKillDelayPublisher;
import org.wangle.seckill.redis.RLock;
import org.wangle.seckill.utils.RedisUtils;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.UUID;


@Slf4j
@Data
public class SecKillConsumer {

    private String name;

    @Reference
    private OrdersProvider orderService;

    @Reference
    private GoodsProvider goodsService;

    @Resource
    private SecKillDelayPublisher delayPublisher;


    private RedisTemplate<String, Object> redisTemplate = RedisUtils.getRedisTemplate();


    public SecKillConsumer(String name) {
        this.name = name;
    }

    @RabbitListener(queues = SecKillProperties.secKillQueue,containerFactory = "simpleContainerFactory")
    @Transactional
    public void consumerMsg(String  order, Channel channel, Message message){
        Orders orders = JSON.parseObject(order, Orders.class);
        Integer goodsId = orders.getGoodsId();
        Integer userId = orders.getUserId();
        log.info(name+"用户【"+orders.getUserId()+"】消费消息，开始创建欲付款订单");
        String uuid = UUID.randomUUID().toString();
        try {
            orders.setCreateDate(LocalDateTime.now());
            //防止消息重复消费
            Boolean member = redisTemplate.opsForSet().isMember(SecKillProperties.goods_buyer_finish_key + goodsId, userId);
            if(member == null || !member){
                //保存抢购订单
                orderService.save(orders);
                String s = UUID.randomUUID().toString();
                //添加分布式锁
                doHandler(orders.getGoodsId(), uuid ,orders);
            }
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);

        } catch (Exception e) {

            log.info(name+"用户【"+orders.getUserId()+"】创建欲付款订单失败");
            log.info("异常：{}", "", e.fillInStackTrace());
            //数据库中添加库存
            //redis缓存中添加库存
            RedisTemplate<String, Object> redisTemplate = RedisUtils.getRedisTemplate();
            redisTemplate.opsForValue().increment(SecKillProperties.goods_nums_key+orders.getGoodsId());
            //1.可以将生成订单的错误原因和当前订单的信息存入数据库中
            //2.也可以直接投入死信队列，在死信队列重新添加库存
            try {
                channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
            }catch (Exception es){
                es.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            //RLock.unLock(SecKillProperties.goods_key+goodsId, uuid);
        }
    }





    public Object doHandler(Integer goodsId, String userId,Orders orders){
        //RLock.tryLock(SecKillProperties.goods_key+goodsId, userId);
        //消减库存
        //goodsService.decrementStock(goodsId);
        Goods goods = goodsService.getById(goodsId);

        goods.setStock(goods.getStock()-1);
        goodsService.updateById(goods);
        //发送欲付款消息
        delayPublisher.sendMsg(orders);
        //存入欲付款用户，防止重复消费
        redisTemplate.opsForSet().add(SecKillProperties.goods_buyer_finish_key + goodsId, userId);
        //手动应答
        log.info(name+"用户【"+orders.getUserId()+"】创建欲付款订单成功");
        return new Object();
    }

    public static void main(String[] args) {
        System.out.println(new Date());
    }

}
